import 'dart:io';

import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:flutter/foundation.dart';

import '../manager/UserInfoManager.dart';
import '../utils/path_provider_utils.dart';
import '../utils/permission_utils.dart';
import '../utils/toast_utils.dart';
import 'Code.dart';
import 'DioLogInterceptor.dart';
import 'Loading.dart';
import 'ResponseInterceptors.dart';
import 'ResultData.dart';
import 'UrlPath.dart';

///
/// 核心工具类，提供get和post请求入口
///
class HttpManager {
  static final HttpManager _instance = HttpManager._internal();

  //连接时间 毫秒
  static const CONNECT_TIMEOUT = Duration(milliseconds: 60000);
  static const UPLOAD_CONNECT_TIMEOUT = Duration(milliseconds: 600000);

  // 接收时间 毫秒
  static const RECEIVE_TIMEOUT = Duration(milliseconds: 60000);
  static const UPLOAD_RECEIVE_TIMEOUT = Duration(milliseconds: 600000);

  late Dio _dio;

  static HttpManager getInstance({String? baseUrl}) {
    if (baseUrl == null) {
      return _instance._normal();
    } else {
      return _instance._baseUrl(baseUrl);
    }
  }

  /// 重新加载
  void reloadToken() {
    Map<String, dynamic> headers = Map();
    // headers['Cookie'] = Cookie("token",LoginModel.userInfo!.token!);
    // headers['Cookie'] = Cookie("userId",LoginModel.userInfo!.id!);
    // headers['Cookie'] = Cookie("appCode",'efficiency_inspector');
    // headers['Cookie'] = Cookie("type",'1');

    /// 自定义Header头部
    Map<String, dynamic> httpHeaders = {
      'token': UserInfoManager().getToken(),
      'userId': UserInfoManager().getUserId(),
      'tenantId': UserInfoManager().getTenantId(),
      'appCode': UserInfoManager().getAppCode(),
      'type': '1',
    };

    _dio.options.headers = httpHeaders;
  }

  /// 单例
  HttpManager._internal() {
    _dio = Dio(BaseOptions(
      baseUrl: UrlPath.baseUrl,
      connectTimeout: CONNECT_TIMEOUT,
      receiveTimeout: RECEIVE_TIMEOUT,
      validateStatus: (status) {
        // 不使用http状态码判断状态，使用AdapterInterceptor来处理（适用于标准REST风格）
        return true;
      },
      responseType: ResponseType.json,
    ));

    // _dio.interceptors.add(new LogInterceptor());
    if (kDebugMode) {
      _dio.interceptors.add(DioLogInterceptor());
    }
    _dio.interceptors.add(ResponseInterceptors());
    var adapter = (_dio.httpClientAdapter as IOHttpClientAdapter);
    adapter.createHttpClient = () {
      var client = HttpClient();
      client.badCertificateCallback =
          (X509Certificate cert, String host, int port) {
        return true;
      };
      return client;
    };
  }

  //一般请求，默认域名
  HttpManager _normal() {
    if (_dio != null) {
      if (_dio.options.baseUrl != UrlPath.baseUrl) {
        _dio.options.baseUrl = UrlPath.baseUrl;
      }
    }
    reloadToken();
    return this;
  }

  //用于指定特定域名
  HttpManager _baseUrl(String baseUrl) {
    _dio.options.baseUrl = baseUrl;
    reloadToken();
    return this;
  }

  ///通用的GET请求
  get(String api, {params, withLoading = true, CancelToken? cancelToken}) async {
    if (withLoading) {
      Loading.show();
    }
    Response response;
    try {
      response = await _dio.get(api, queryParameters: params, cancelToken: cancelToken);
      if (withLoading) {
        Loading.dismiss();
      }
    } on DioException catch (e) {
      if (withLoading) {
        Loading.dismiss();
      }
      return resultError(e);
    }
    if (response.data is DioException) {
      return resultError(response.data['code']);
    }
    return response.data;
  }

  ///通用的POST请求
  post(api, {params, bool withLoading = true, CancelToken? cancelToken}) async {
    if (withLoading) {
      Loading.show();
    }
    Response response;
    try {
      response = await _dio.post(api, data: params, cancelToken: cancelToken);
      if (withLoading) {
        Loading.dismiss();
      }
    } on DioException catch (e) {
      if (withLoading) {
        Loading.dismiss();
      }
      return resultError(e);
    }
    if (response.data is DioException) {
      return resultError(response.data['code']);
    }
    return response.data;
  }

  /// 单文件上传
  uploadFile(
    api, {
    required MultipartFile multipartFile,
    bool withLoading = true,
    CancelToken? cancelToken,
    ProgressCallback? onSendProgress,
  }) async {
    FormData formData = FormData.fromMap({'file': multipartFile});
    Response response;
    try {
      _dio.options.sendTimeout = UPLOAD_CONNECT_TIMEOUT;
      _dio.options.receiveTimeout = UPLOAD_RECEIVE_TIMEOUT;
      response = await _dio.post(api, data: formData, cancelToken: cancelToken, onSendProgress: (int sent, int total) {
        if (onSendProgress != null) {
          onSendProgress(sent, total);
        } else {
          Loading.showProgress(sent / total, status: '上传中...');
        }
      });
      if (withLoading) {
        Loading.dismiss();
      }
    } on DioException catch (e) {
      if (kDebugMode) {
        print(e);
      }
      if (withLoading) {
        Loading.dismiss();
      }
      return resultError(e);
    }
    if (response.data is DioException) {
      return resultError(response.data['code']);
    }
    return response.data;
  }

  /// 多上传文件
  uploadFiles(
    api, {
    required List<MultipartFile> multipartFiles,
    bool withLoading = true,
    CancelToken? cancelToken,
    ProgressCallback? onSendProgress,
  }) async {
    FormData formData = FormData.fromMap({'files': multipartFiles});
    Response response;
    try {
      _dio.options.sendTimeout = UPLOAD_CONNECT_TIMEOUT;
      _dio.options.receiveTimeout = UPLOAD_RECEIVE_TIMEOUT;
      response = await _dio.post(api, data: formData, cancelToken: cancelToken, onSendProgress: (int sent, int total) {
        if (onSendProgress != null) {
          onSendProgress(sent, total);
        } else {
          Loading.showProgress(sent / total, status: '上传中...');
        }
      });
      if (withLoading) {
        Loading.dismiss();
      }
    } on DioException catch (e) {
      if (kDebugMode) {
        print(e);
      }
      if (withLoading) {
        Loading.dismiss();
      }
      return resultError(e);
    }
    if (response.data is DioException) {
      return resultError(response.data['code']);
    }
    return response.data;
  }

  /// 分片上传
  upload(
    api, {
    required FormData formData,
    bool withLoading = true,
    CancelToken? cancelToken,
    ProgressCallback? onSendProgress,
  }) async {
    Response response;
    try {
      _dio.options.sendTimeout = UPLOAD_CONNECT_TIMEOUT;
      _dio.options.receiveTimeout = UPLOAD_RECEIVE_TIMEOUT;
      response = await _dio.post(api, data: formData, cancelToken: cancelToken, onSendProgress: (int sent, int total) {
        if (onSendProgress != null) {
          onSendProgress(sent, total);
        } else {
          if (withLoading) {
            Loading.showProgress(sent / total, status: '上传中...');
          }
        }
      }, onReceiveProgress: (int count, int total) {
        // Loading.show(status: '保存中...');
      });
      if (withLoading) {
        Loading.dismiss();
      }
    } on DioException catch (e) {
      if (kDebugMode) {
        print(e);
      }
      if (withLoading) {
        Loading.dismiss();
      }
      return resultError(e);
    }

    if (response.data is DioException) {
      return resultError(response.data['code']);
    }

    return response.data;
  }

  /// 下载文件
  downLoad(
    String urlPath,
    String fileName, {
    bool withLoading = true,
    CancelToken? cancelToken,
    ProgressCallback? onReceiveProgress,
  }) async {
    late Response response;

    /// 请求 文件读取权限，后检查是否被授权，
    if (await PermissionUtils().getStorageState()) {
      // Either the permission was already granted before or the user just granted it.

      // 文件路径
      String savePath = "${await PathProviderUtils().getAppSupPath()}/$fileName";
      Dio dio = Dio();
      if (kDebugMode) {
        print(savePath);
      }
      try {
        response = await dio.download(urlPath, savePath, cancelToken: cancelToken, onReceiveProgress: (int count, int total) {
          if (onReceiveProgress != null) {
            onReceiveProgress(count, total);
          } else {
            Loading.showProgress(count / total, status: "下载中...");
          }
        });

        if (withLoading) {
          Loading.dismiss();
        }
      } on DioException catch (e) {
        if (kDebugMode) {
          print(e);
        }
        if (withLoading) {
          Loading.dismiss();
        }
        return resultError(e);
      }

      if (response.data is DioException) {
        return resultError(response.data['code']);
      }
    }
    return response;
  }
}

ResultData resultError(DioException e) {
  Response errorResponse;
  if (e.response != null) {
    errorResponse = e.response!;
  } else {
    errorResponse = Response(statusCode: 666, requestOptions: RequestOptions(path: ""));
  }
  if (e.type == DioExceptionType.connectionTimeout || e.type == DioExceptionType.receiveTimeout || e.type == DioExceptionType.sendTimeout) {
    toast.show("网络超时");
    errorResponse.statusCode = Code.NETWORK_TIMEOUT;
  } else if (e.type == DioExceptionType.badResponse) {
    toast.show("网络错误");
    errorResponse.statusCode = Code.NETWORK_ERROR;
  } else if (e.type == DioExceptionType.cancel) {
    toast.show("请求取消");
    errorResponse.statusCode = Code.NETWORK_CANCEL;
  } else {
    errorResponse.statusCode = Code.ERROR;
    toast.show("网络异常");
  }
  return ResultData(errorResponse.statusMessage, false, errorResponse.statusCode!);
}
